<script setup lang="ts">
import {
  useMessage,
  NForm,
  NFormItem,
  NInput,
  NSelect,
  type FormInst,
  NButton,
  NDatePicker,
  NTreeSelect,
  NIcon,
  type TreeSelectOption,
  NConfigProvider,
  NAvatar,
  NUpload,
  NScrollbar,
  type UploadCustomRequestOptions,
  type UploadInst
} from 'naive-ui'
import { CloseCircle } from '@vicons/ionicons5'
import { onMounted, ref, shallowRef } from 'vue'
import { sendRequest } from '@/utils/api'
import type { UserInfoModel, UserPositionModel, PartyOrganizationModel } from '@/api/user'
import type { HttpResponse, HttpResponsePagination } from '@/utils/http'
import FixedAction from '@/components/FixedAction.vue'
import type { InstitutionTreeModel } from '@/api/sysInstitution'
import type { PositionTableRowModel } from '@/api/sysPosition'
import type { DicTreeModel } from '@/api/dic'
import { useRoute } from 'vue-router'
import { format } from 'date-fns'
import useRouteReplace from '@/hooks/useRouteReplace'
import { usePermissionStore } from '@/stores/permission'
import { cardNumberRegex } from '@/enums/regex'

type Nullable<T> = { [P in keyof T]: T[P] | null }

const message = useMessage()
const route = useRoute()
const permissionStore = usePermissionStore()
const routeReplace = useRouteReplace(route.query.redirect as string)

const formInst = shallowRef<FormInst | null>(null)
const formData = ref({} as UserInfoModel)
const submitLoading = ref(false)

const rules = {
  accountName: {
    required: false,
    trigger: ['input', 'blur'],
    validator: (_: any, value: any) => {
      // if (value?.length > 10) return new Error('开户名 字数不得超过10')
      return true
    }
  },
  openingBank: {
    required: false,
    trigger: ['input', 'blur'],
    validator: (_: any, value: any) => {
      // if (value?.length > 100) return new Error('开户行 字数不得超过100')
      return true
    }
  },
  bankCardNumber: {
    required: false,
    trigger: ['input', 'blur'],
    validator: (_: any, value: any) => {
      return true
    }
  }
}

const handleSubmit = () => {
  if (submitLoading.value) return
  formInst.value?.validate(async (error) => {
    if (error) return

    try {
      submitLoading.value = true
      const [error, res] = await sendRequest<HttpResponse<UserInfoModel>>({
        module: 'user',
        api: 'update',
        override: {
          data: {
            ...formData.value,
            carNumberList: formData.value.carNumberList.filter(Boolean)
          }
        }
      })

      if (error) return message.error(error.message)
      if (res.code !== 0) message.error(res.msg)
      window.flags.flushUser = true
      routeReplace()
    } catch (error) {
      console.log(error)
    } finally {
      submitLoading.value = false
    }
  })
}

// 职位列表
const positionList = shallowRef<PositionTableRowModel[]>([])
const queryPositionList = async () => {
  try {
    const [error, res] = await sendRequest<HttpResponsePagination<PositionTableRowModel>>({
      module: 'sysPosition',
      api: 'list',
      override: {
        params: {
          limit: 100000
        }
      }
    })

    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    positionList.value = res.data.list
  } catch (error) {
    console.log(error)
  }
}

// 部门列表
const treeOptions = shallowRef<InstitutionTreeModel[]>([])
const treeLoading = ref(false)
const queryTreeOptions = async () => {
  try {
    treeLoading.value = true
    const [error, res] = await sendRequest<HttpResponse<InstitutionTreeModel[]>>({
      module: 'sysInstitution',
      api: 'getTree'
    })

    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    treeOptions.value = res.data
  } catch (error) {
    console.log(error)
  } finally {
    treeLoading.value = false
  }
}
const deptOptions = ref<Nullable<Partial<UserPositionModel>>[]>([
  {
    deptId: null,
    positionId: null
  }
])
// @ts-ignore
formData.value.userPositionList = deptOptions.value

// 车牌号列表
const carNumberList = ref<(string | null)[]>([])
// @ts-ignore
formData.value.carNumberList = carNumberList.value
const handleAddCarNumber = () => {
  carNumberList.value.push(null)
}
const handleDeleteCarNumber = (index: number) => {
  carNumberList.value.splice(index, 1)
}

// 政治面貌
const politicalOptions = ref<DicTreeModel[] | undefined>()
const queryPoliticalOptions = async () => {
  const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
    module: 'dic',
    api: 'getTree',
    override: {
      params: {
        dicCode: 'A22'
      }
    }
  })

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  politicalOptions.value = res.data[0]?.children
}

// 党职位
const partyPositionOptions = ref<DicTreeModel[] | undefined>()
const queryPartyPositionOptions = async () => {
  const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
    module: 'dic',
    api: 'getTree',
    override: {
      params: {
        dicCode: 'A18'
      }
    }
  })

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  partyPositionOptions.value = res.data[0]?.children
}
// 党组织
const partyOrganizationOptions = ref<DicTreeModel[] | undefined>()
const queryPartyOrganizationOptions = async () => {
  const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
    module: 'dic',
    api: 'getTree',
    override: {
      params: {
        dicCode: 'A17'
      }
    }
  })

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  partyOrganizationOptions.value = res.data[0]?.children
}

const userPartyList = ref<Nullable<Partial<PartyOrganizationModel>>[]>([])
// @ts-ignore
formData.value.userPartyList = userPartyList.value

const uploadInst = ref<UploadInst | null>(null)
const handleUpdateAvatar = async ({
  file,
  onFinish,
  onError,
  onProgress
}: UploadCustomRequestOptions) => {
  const form = new FormData()
  form.append('file', file.file as File)

  try {
    const [error, res] = await sendRequest({
      module: 'upload',
      api: 'uploadFile',
      override: {
        data: form,
        onUploadProgress({ progress }) {
          onProgress({ percent: progress || 0 })
        }
      }
    })
    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    formData.value.headSculpture = res.data.url
    onFinish()
  } catch (error: any) {
    onError()
    message.error(error.message)
  }
}

const queryUserInfo = async () => {
  formData.value = {} as UserInfoModel
  deptOptions.value = []
  carNumberList.value = []
  userPartyList.value = []

  try {
    const [error, res] = await sendRequest<HttpResponse<UserInfoModel>>({
      module: 'user',
      api: 'detailInfo',
      uri: {
        id: permissionStore.userInfo?.id!
      }
    })
    if (error) return message.error(error.message)
    if (res.code !== 0) return message.error(res.msg)
    if (res.data.partyTime) res.data.partyTime = format(new Date(res.data.partyTime), 'yyyy-MM-dd')
    if (res.data.birthday) res.data.birthday = format(new Date(res.data.birthday), 'yyyy-MM-dd')
    formData.value = {
      ...res.data
    }
    deptOptions.value = res.data.userPositionList
    carNumberList.value = res.data.carNumberList
    userPartyList.value = res.data.userPartyList
  } catch (error) {
    console.log(error)
  }
}

onMounted(() => {
  queryTreeOptions()
  queryPositionList()
  queryPoliticalOptions()
  queryPartyPositionOptions()
  queryPartyOrganizationOptions()
  queryUserInfo()
})
</script>

<template>
  <NConfigProvider abstract :theme-overrides="{
    Form: {
      labelTextColor: 'rgba(0,0,0,0.85)'
    }
  }">
    <div class="add-user">
      <NScrollbar>
        <div class="form">
          <NForm :disabled="submitLoading" :model="formData" :rules="rules" ref="formInst" label-placement="left"
            require-mark-placement="left" label-width="100rem">
            <NFormItem label="员工编号：">
              <NInput placeholder="/" :value="formData.userNumber" disabled />
            </NFormItem>
            <NFormItem label="姓名：" class="name">
              <NInput placeholder="请输入" v-model:value="formData.userName" />
            </NFormItem>
            <NFormItem label="性别：" class="sex">
              <NSelect v-model:value="formData.sex" :options="[
                {
                  label: '男',
                  value: 1
                },
                {
                  label: '女',
                  value: 2
                }
              ]" />
            </NFormItem>

            <NFormItem label="生日：" class="birthday">
              <NDatePicker input-readonly value-format="yyyy-MM-dd" v-model:formatted-value="formData.birthday" />
            </NFormItem>
            <!-- 开户名，开户行 -->
            <div class="col2">
              <NFormItem label="开户名：" path="accountName">
                <NInput placeholder="请输入" v-model:value="formData.accountName" />
              </NFormItem>
              <NFormItem label="开户行：" path="openingBank">
                <NInput placeholder="请输入" v-model:value="formData.openingBank" />
              </NFormItem>
            </div>
            <NFormItem label="银行卡号：" path="bankCardNumber">
              <NInput placeholder="请输入" v-model:value="formData.bankCardNumber" />
            </NFormItem>
            <NFormItem label="部门职位：" />
            <div class="bg-wrapper">
              <div class="col2" v-for="(item, i) in deptOptions" :key="i">
                <NFormItem label="部门：">
                  <NTreeSelect disabled :options="(treeOptions as unknown as TreeSelectOption[])" placeholder="/"
                    key-field="id" label-field="name" :value="item.deptId" />
                </NFormItem>
                <NFormItem label="职位：">
                  <NTreeSelect disabled :options="(positionList as unknown as TreeSelectOption[])" placeholder="/"
                    key-field="id" label-field="positionName" :value="item.positionId" />
                </NFormItem>
              </div>
            </div>

            <NFormItem label="办公电话：">
              <NInput placeholder="请输入" v-model:value="formData.officePhone" />
            </NFormItem>

            <NFormItem label="手机号码：">
              <NInput placeholder="请输入" v-model:value="formData.phone" />
            </NFormItem>

            <NFormItem label="电子邮箱：">
              <NInput placeholder="请输入" v-model:value="formData.mail" />
            </NFormItem>

            <NFormItem label="车牌号：">
              <NButton color="#6CB187" ghost @click="handleAddCarNumber">
                新增车牌号
              </NButton>
            </NFormItem>
            <div class="col2">
              <NFormItem label="车牌号：" v-for="(_, i) in carNumberList" :key="i">
                <NInput placeholder="请输入" v-model:value="carNumberList[i]">
                  <template #suffix>
                    <NIcon color="#fd4a29" size="24rem" style="cursor: pointer" @click="handleDeleteCarNumber(i)">
                      <CloseCircle />
                    </NIcon>
                  </template>
                </NInput>
              </NFormItem>
            </div>

            <NFormItem label="头像：">
              <NUpload ref="uploadInst" :custom-request="handleUpdateAvatar" :accept="'image/*'" :max="1" abstract>
                <NButton ghost color="#5FB17F" @click="uploadInst?.openOpenFileDialog()">
                  修改头像
                </NButton>
              </NUpload>
            </NFormItem>
            <NAvatar style="margin-left: 100rem" :src="formData.headSculpture" :size="150" />
          </NForm>
        </div>
      </NScrollbar>
    </div>
  </NConfigProvider>

  <FixedAction>
    <div class="add-user-buttons">
      <NButton color="#999999" ghost :disabled="submitLoading" @click="routeReplace">
        取消
      </NButton>

      <NButton color="#5FB17F" :disabled="submitLoading" :loading="submitLoading" @click="handleSubmit">
        确定
      </NButton>
    </div>
  </FixedAction>
</template>

<style scoped lang="scss">
.add-user {
  flex: 1;
  padding: 25rem 56rem 110rem 36rem;
  width: 100%;
  height: 100%;
  overflow: hidden;

  .n-input,
  .n-tree-select,
  .n-date-picker,
  .n-select {
    width: 400rem;
  }

  .form {
    width: 100%;
    padding: 25rem 33rem 27rem 20rem;
    background-color: #ebeceb;

    .n-form {
      width: 70%;
      margin: 0 auto;
    }
  }

  .with-avatar {
    display: grid;
    grid-template-areas:
      'name avatar'
      'sex avatar'
      'birthday avatar';

    .name {
      grid-area: name;
    }

    .sex {
      grid-area: sex;
    }

    .birthday {
      grid-area: birthday;
    }

    .avatar {
      grid-area: avatar;
      align-self: center;
      justify-self: center;
      display: flex;
      align-items: flex-end;
      gap: 0 1em;
    }
  }

  .col2 {
    position: relative;
    display: grid;
    grid-template-columns: repeat(2, auto);
    gap: 0 60rem;

    .item-close {
      position: absolute;
      top: 5rem;
      right: -48rem;
      display: flex;
      align-items: center;
      font-size: 24rem;
      cursor: pointer;
      color: #fd4a29;
      transition: all ease-in-out 0.3s;

      &:hover {
        opacity: 0.8;
      }
    }
  }
}

.add-user-buttons {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0 16rem;

  .n-button {
    width: 100rem;
    height: 50rem;
  }
}
</style>
